/*
 *    Copyright (c) 2014 Xiang Xu <xuxiang@mail.bnu.edu.cn>
 *
 *    Permission is hereby granted, free of charge, to any person
 *    obtaining a copy of this software and associated documentation
 *    files (the "Software"), to deal in the Software without
 *    restriction, including without limitation the rights to use,
 *    copy, modify, merge, publish, distribute, sublicense, and/or sell
 *    copies of the Software, and to permit persons to whom the
 *    Software is furnished to do so, subject to the following
 *    conditions:
 *
 *    The above copyright notice and this permission notice shall be
 *    included in all copies or substantial portions of the Software.
 *
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 *    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 *    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 *    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *    OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef UTILITY_ARGUMENTS_H
#define UTILITY_ARGUMENTS_H

#include "status.h"
#include "boost/program_options.hpp"
#include <boost/concept_check.hpp>
#include <iostream>
#include <string>

/**
 *    This class organize all the variables/parameters that will be used or setted in the whole facade parsing process.
 *
 *    There all two types of variables that will be used:
 *    1. Interal file names. User should not concern this.(eg. raw_pcd_, raw_file, etc)
 *    2. Algorithm parameters. User can set these parameter through a parameter.json file. (eg. resolution_, episodes_, etc)
 */
class Arguments
{
public:
    Arguments();
    ~Arguments() {}

    //Function to parse arguments from command line
    Status Parse(int argc, char** argv);

    Status SaveSpatialScale(double xmin, double ymin, double zmin, double xmax,
                            double ymax, double zmax);

    inline std::string& GetWorkingFolder()
    {
        return working_folder_;
    }
    inline std::string& GetRawFile()
    {
        return raw_file_;
    }
    inline std::string& GetFacadeFile()
    {
        return raw_pcd_;
    }
    inline std::string& GetFacadeTransformedFile()
    {
        return rt_pcd_;
    }
    inline std::string& GetFacadePlaneTransformedFile()
    {
        return pt_pcd_;
    }
    inline std::string& GetGrammarFile()
    {
        return grammar_file_;
    }
    inline std::string& GetGridFile()
    {
        return grid_;
    }
    inline std::string& GetSpatialScaleFile()
    {
        return spatial_scale_;
    }
    inline std::string& GetSVMModelFile()
    {
        return svm_model_file_;
    }
    inline std::string& GetQFile()
    {
        return q_file_;
    }
    inline std::string& GetActionParameterFile()
    {
        return action_parameters_file_;
    }
    inline std::string& GetResultImageFile()
    {
        return result_png_;
    }
    inline std::string& GetResultAsciiFile()
    {
        return result_txt_;
    }
    inline std::string& GetResultValidateFile()
    {
        return original_result_overlap_png_;
    }

    inline std::vector<double>& GetSampleLeafSize()
    {
        return leaf_size_;
    }
    inline std::vector<double>& GetRadiusOutlierParameters()
    {
        return radius_outlier_remover_;
    }
    inline std::vector<double>& GetStatisticalOutlierParameters()
    {
        return statiscal_outlier_remover_;
    }
    inline std::vector<double>& GetSymbolWeights()
    {
        return weights_;
    }

    inline double GetPlaneThreshold()
    {
        return plane_distance_threshold_;
    }
    inline double GetResolution()
    {
        return resolution_;
    }
    inline bool LoadSVMModel()
    {
        return load_svm_model_;
    }
    inline bool LoadQTable()
    {
        return load_qtable_;
    }
    inline bool StateGroup()
    {
        return state_grouping_;
    }
    inline int GetLearningRate()
    {
        return learnning_rate_;
    }
    inline int GetLearningEpisodes()
    {
        return episodes_;
    }
    inline int GetGreedyLearningEpisodes()
    {
        return g_episodes_;
    }

private:
    bool ParseCommandLine(int argc, char** argv);
    Status ReadParameters();

    // This is the only input parameter: the working folder
    // this folder contains the parameter configure file, point cloud file and all the interal files.
    // User only need to prepare their configure file and data in a folder and feed the path of this
    // folder to programs, the programs will automatic parse all the parameters that will be used.
    std::string working_folder_;

    // parameter configure files
    // MUST named as configure.json
    std::string parameter_file_;

    // shape grammar file
    // MUST named as grammar.json
    std::string grammar_file_;

    // raw point cloud file in .pcd format
    // This is the point cloud format that we deal with
    // MUST named as raw.pcd
    std::string raw_pcd_;

    // If we have different format point cloud
    // such as(current support: raw.xyz and raw.ply and raw.xyzl)
    std::string raw_file_;

    // Interal files
    std::string rt_pcd_;		// transformed point cloud
    std::string pt_pcd_;		// transformed point cloud plane

    // leaf size when do grid sampling
    std::vector<double> leaf_size_;

    // parameters for outlier remover
    std::vector<double> radius_outlier_remover_;
    std::vector<double> statiscal_outlier_remover_;

    // spatial scale of facade cloud.
    std::string spatial_scale_;

    // threshold when extracing plane
    double plane_distance_threshold_;

    // resolution when rasterize the facade plane
    double resolution_;

    // facade grid, contains the features
    std::string grid_;

    // svm model file
    std::string svm_model_file_;
    // whether use provided svm model file
    bool load_svm_model_;

    // actions
    std::string action_parameters_file_;

    // q table
    std::string q_file_;
    bool load_qtable_; // 0 -- not load; 1 -- load.

    // open state grouping or not
    bool state_grouping_;

    // RL variables
    double episodes_;
    double g_episodes_;
    double learnning_rate_;

    // wights for each symbol when learning
    std::vector<double> weights_;


    // result
    std::string result_png_;
    std::string result_txt_;
    std::string original_result_overlap_png_;
};

#endif // !UTILITY_ARGUMENTS_H

